from django.contrib.auth import authenticate
from django.contrib.auth.hashers import make_password, check_password
from rest_framework.views import APIView
from rest_framework.response import Response
from django.http import HttpResponse

import re
import redis
import uuid
import requests

from .models import User, AuthUser, UserToken
from .serializer import UserModelSerializer, AuthUserModelSerializer
from myutils.common import create_token, check_token, login_token
from .tasks import send_mail_task
from myutils.captcha.captcha import captcha


r1 = redis.Redis(db=1)

"""
pip install celery==4.4.7
pip install redis==3.5.3
pip install eventlet==0.26.1
"""


class CheckCodeView(APIView):
    """
    验证码验证
    """
    def get(self, request):
        image_id = request.query_params.get('image_id')
        image_code = request.query_params.get('image_code')
        # 通过image_id去redis中获取验证码文本
        code_text = r1.get(image_id).decode()
        if image_code.lower() == code_text.lower():
            return Response({'msg': 'OK', 'code': 200})
        else:
            return Response({'msg': '验证码不正确', 'code': 400})


class CreateUUIDView(APIView):
    """
    uuid接口，供前端生成图片验证码使用
    """
    def get(self, request):
        image_id = str(uuid.uuid4())
        return Response({'msg': 'ok', 'image_id': image_id, 'code': 200})


class VerifyCodeView(APIView):
    """
    生成图片验证码
    """
    def get(self, request):
        # 获取图片的id
        image_id = request.query_params.get('image_id')
        # 生成图片是元组格式，需要用两个参数进行接收
        text, image = captcha.generate_captcha()
        # 把文本内容存入redis
        r1.setex(image_id, 60, text)
        # 把图片返回页面
        return HttpResponse(image, 'image/png')
        # return HttpResponse('<h1 style="color: red">Hello World</h1>')


class RegisterView(APIView):
    """
    @ author: donghaiming
    @ date: 2020-10-26
    用户注册：需要提供以下数据
        用户名、密码、确认密码、邮箱
    """
    authentication_classes = []

    def post(self, request):
        """
        {'username': ['zhangsan'], 'password1': ['123'], 'password2': ['123'], 'email': ['zhangsan123@qq.com']}
        """
        username = request.data.get('username')
        password1 = request.data.get('password1')
        password2 = request.data.get('password2')
        email = request.data.get('email')

        # 判断数据完整
        if not all([username, password1, password2, email]):
            return Response({'msg': '数据不完整', 'code': 400})

        # 正则验证邮箱
        ex_email = re.compile(r'^.*@[a-zA-Z0-9]{2,3}.com')
        if not re.match(ex_email, email):
            return Response({'msg': '邮箱格式不正确', 'code': 400})

        # 判断用户是否存在
        user_obj = User.objects.filter(username=username).first()
        if user_obj:
            return Response({'msg': '用户已注册', 'code': 400})

        # 两次密码验证
        if password1 == password2:
            # 构造数据
            user_data = {'username': username, 'password': make_password(password1), 'email': email}
            user_serializer = UserModelSerializer(data=user_data)
            # 校验数据
            if user_serializer.is_valid():
                user_serializer.save()
                print(user_serializer.data)
                user_id = user_serializer.data.get('id')
                token = create_token(user_id)
                # 异步发送邮件
                send_mail_task.delay(username, email, token)
                return Response({'msg': '注册成功', 'code': 200})
            else:
                return Response({'error': user_serializer.errors, 'code': 400})
        else:
            return Response({'msg': '两次密码不一致', 'code': 400})

# celery -A mdpro worker -l info -P eventlet


class CheckUsername(APIView):

    def get(self, request):
        username = request.query_params.get('username')
        user_obj = User.objects.filter(username=username)
        if user_obj:
            return Response({'msg': '用户已存在', 'code': 400})
        else:
            return Response({'msg': 'OK', 'code': 200})


class ActiveView(APIView):

    def get(self, request):
        token = request.query_params.get('token')
        user_info = check_token(token)
        if user_info:
            # 反序列化修改
            # 1、查找用户对象
            user_obj = User.objects.get(pk=user_info.get('user_id'))
            # 2、封装要修改的数据
            user_data = {'is_active': 1}
            # instance要修改的对象
            # partial 允许修改的字段，不加这一项的话，默认修改全部
            user_serializer = UserModelSerializer(instance=user_obj, data=user_data, partial=True)
            # 校验数据
            if user_serializer.is_valid():
                # 保存数据
                user_serializer.save()
                return Response({'msg': '激活成功', 'code': 200})
        else:
            print('No')
        return Response({'msg': user_info})

# authenticate


class LoginView(APIView):
    """
    用户登录，使用django自带的认证
    """
    def post(self, request):
        # 网页数据提取
        username = request.data.get('username')  # zhangsan
        password = request.data.get('password')  # 123
        # 使用django自带的模块进行认证
        user = authenticate(username=username, password=password)
        # 判断用户
        if user:
            # 在这里添加jwt
            user_id = user.pk
            token = login_token(user_id)
            # 用户登录成功以后，存入token  update_or_create()   存在时更新，不存在时进行创建
            UserToken.objects.update_or_create(user=user, defaults={'token': token})
            return Response({'msg': 'OK', 'code': 200, 'user_id': user.pk, 'token': token, 'username': username})
        else:
            return Response({'msg': '登录失败', 'code': 400})


"""
pip install requests
"""


class AcquireAccessTokenView(APIView):

    def get(self, request):
        code = request.query_params.get('code')
        # 请求地址
        request_url = 'https://api.weibo.com/oauth2/access_token'
        # 请求参数
        request_data = {
            'client_id': '1923644635',
            'client_secret': '9b6396ca9a664a776e534998dd0739bc',
            'grant_type': 'authorization_code',
            'code': code,
            'redirect_uri': 'http://127.0.0.1:8080/callback'
        }
        # 使用requests.post进行数据请求
        res = requests.post(url=request_url, data=request_data)
        # 获取到用户token信息和id
        # 使用json()方法获取返回数据中的json数据
        # text   获取返回数据中的文本
        # content 获取返回数据中的二进制流
        user_token = res.json()
        print(user_token)
        # 获取用户id
        uid = user_token.get('uid')
        token = login_token(user_id=uid)

        # 去获取三方表的对象，用来判断用户是否进行关联
        auth_user = AuthUser.objects.filter(weibo=uid)
        if auth_user:
            return Response({'msg': 'Ok', 'code': 200, 'uid': uid, 'token': token})
        else:
            return Response({'msg': '用户未绑定', 'code': 400, 'uid': uid})


class UserBindView(APIView):
    """
    用户绑定视图
    """
    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        uid = request.data.get('uid')
        # 查找用户对象，用来判断用户是否存在
        user_obj = User.objects.filter(username=username).first()
        if user_obj and check_password(password, user_obj.password):
            authuser_data = {'user': user_obj.pk, 'weibo': uid}
            authuser_serializer = AuthUserModelSerializer(data=authuser_data)
            if authuser_serializer.is_valid():
                # 绑定成功，保存数据
                authuser_serializer.save()
                token = login_token(user_id=uid)
                return Response({'msg': '绑定成功', 'code': 200, 'token': token, 'username': username})
            else:
                # 没绑定成功，抛出异常
                return Response({'error': authuser_serializer.errors, 'code': 400})

        else:
            return Response({'msg': '绑定的用户名或者密码不正确', 'code': 400})


class UserInfoView(APIView):
    """
    个人信息展示
    """
    # authentication_classes = [Authentions]

    def get(self, request):
        # self.dispatch
        return Response({'msg': 'OK'})

